/**
* COPYRIGHT. whx. ALL RIGHTS RESERVED.
* Project: just-core
* Author: whx <harrywu304@gmail.com>
* Create On: Apr 11, 2012 8:21:36 PM
*/

package org.justframework.api.dispatcher;

import java.lang.reflect.Method;

import org.justframework.api.connector.Request;
import org.justframework.api.connector.Response;
import org.justframework.api.exception.ResourceNotFoundException;
import org.justframework.core.mapper.MapperFactory;
import org.justframework.server.ResourceLocator;
import org.justframework.util.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * restful dispatcher
 */
public class RestDispatcher extends BaseDispatcher {
	
	/**
	 * logger
	 */
	private static Logger logger = LoggerFactory.getLogger(RestDispatcher.class);

	/* (non-Javadoc)
	 * @see org.justframework.api.dispatcher.BaseDispatcher#doHandle(org.justframework.api.connector.Request, org.justframework.api.connector.Response, org.justframework.server.RequestContext)
	 */
	@Override
	public void doDispatch(Request request, Response response,
			RequestContext context) throws Exception {
		//locate resource
		Class klass = ResourceLocator.locate(request.getUri().getPath(),request.getParams());
		
		//if no resource class can be found, throw ResourceNotFoundException exception
		if(klass == null){
			String msg = "can not found resource class for [" + request.getUri().getPath() + "]";
			logger.error(msg);
			throw new ResourceNotFoundException(msg);
		}
		
		//invoke corresponding resource class and method
		logger.debug("located resource class:{}", klass);
			String requestMethod = request.getRequestMethod().toString().toLowerCase();
			Method method = klass.getMethod(requestMethod, Request.class, Response.class);
			if(method == null){
				String msg = "can not found method ["+requestMethod+"] for class ["+klass+"]";
				logger.error(msg);
				throw new NoSuchMethodException(msg);
			}
			logger.info("located method:{}", method);
			//invoke process method
			method.invoke(klass.newInstance(), request, response);
			//convert resource object to json string except String itself
			//if(!(response.getContent() instanceof String)){
				response.setContent(MapperFactory.getDefaultMapper().toSerial(response.getContent()));
			//}

	}

}
